#include <iostream>
#include <string>
#include <cstring>
// 引入Neon头文件
#include <arm_neon.h>

using namespace std;

// 定义了Byte，便于使用
typedef unsigned char Byte;
// 定义了32比特
typedef unsigned int bit32;

// MD5的一系列参数。参数是固定的
#define s11 7
#define s12 12
#define s13 17
#define s14 22
#define s21 5
#define s22 9
#define s23 14
#define s24 20
#define s31 4
#define s32 11
#define s33 16
#define s34 23
#define s41 6
#define s42 10
#define s43 15
#define s44 21

/**
 * @Basic MD5 functions for 2-way SIMD.
 *
 * @param there bit32.
 *
 * @return one bit32.
 */
// 修改为使用64位向量指令(无q后缀)
#define F2(x, y, z) vorr_u32(vand_u32(x, y), vand_u32(vmvn_u32(x), z))
#define G2(x, y, z) vorr_u32(vand_u32(x, z), vand_u32(y, vmvn_u32(z)))
#define H2(x, y, z) veor_u32(veor_u32(x, y), z)
#define I2(x, y, z) veor_u32(y, vorr_u32(x, vmvn_u32(z)))

/**
 * @Rotate Left for 2-way SIMD.
 *
 * @param {num} the raw number.
 *
 * @param {n} rotate left n.
 *
 * @return the number after rotated left.
 */
#define ROTATELEFT2(num, n) vorr_u32(vshl_n_u32(num, n), vshr_n_u32(num, 32 - n))

#define FF2(a, b, c, d, x, s, ac){ \
  a = vadd_u32(a, vadd_u32(F2(b, c, d), vadd_u32(x, vdup_n_u32(ac)))); \
  a = vadd_u32(ROTATELEFT2(a, s), b); \
}

#define GG2(a, b, c, d, x, s, ac){ \
  a = vadd_u32(a, vadd_u32(G2(b, c, d), vadd_u32(x, vdup_n_u32(ac)))); \
  a = vadd_u32(ROTATELEFT2(a, s), b); \
}

#define HH2(a, b, c, d, x, s, ac){ \
  a = vadd_u32(a, vadd_u32(H2(b, c, d), vadd_u32(x, vdup_n_u32(ac)))); \
  a = vadd_u32(ROTATELEFT2(a, s), b); \
}

#define II2(a, b, c, d, x, s, ac){ \
  a = vadd_u32(a, vadd_u32(I2(b, c, d), vadd_u32(x, vdup_n_u32(ac)))); \
  a = vadd_u32(ROTATELEFT2(a, s), b); \
}

void SIMD_MD5Hash_2(string input[2], bit32 state[2][4]);
